package com.dongluhitec.card.deviceUpdeter.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.dongluhitec.card.deviceUpdeter.Model;
import com.dongluhitec.card.deviceUpdeter.bean.Device;

public class DeviceSearchService {

    public interface DiscoveryCallback {
        void discovery(Device device);
    }
    

    public final Logger LOGGER = LoggerFactory.getLogger(DeviceSearchService.class);
    public final int maxTask = 40;

    private DiscoveryCallback callback;// 
    // 
    private String text_ip = "192.168.1.1";
    private String text_ip1 = "192.168.1.11";
  

	private static Map<String, Device> ipToDeviceMap = new HashMap<>();
    long start_get_ip = System.currentTimeMillis();
    long start_get_ip1;
    // 
    private volatile boolean isRunnable = true;
    private boolean status = false;
    private ExecutorService fixedThreadPool;
    private String localIp;
    private Model model;
    

    public DeviceSearchService(Model model) {
        try {
        	this.model = model;
            localIp = InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            LOGGER.error("获取本机ip时发生错误", e);
        }
    }

    public void setCallback(DiscoveryCallback callback) {
        this.callback = callback;
    }

	public void start(String startIp, String endIp) {
		List<String> ipList = generateAllAvailableIp(startIp, endIp);
		
		fixedThreadPool = Executors.newFixedThreadPool(maxTask);
		for (String ip : ipList) {
			
			fixedThreadPool.submit(() -> {
				try {
					if (!isRunnable || localIp.equals(ip)) {
						return;
					}
					LOGGER.debug("正在搜索ip:{}", ip);
					searchIp(ip);
				} catch (Exception e) {
					LOGGER.error("搜索ip:" + ip + "时发生错误", e);
				}
			});
		}
		fixedThreadPool.shutdown();
		searchMacAtLast();
	}

    private void searchMacAtLast() {
    	this.model.setLabel("正在等待......");
        Runnable runnable = () -> {
            while (!fixedThreadPool.isTerminated()) {
                try {
                    TimeUnit.MILLISECONDS.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            searchMac();
        };
        new Thread(runnable).start();
    }

    private List<String> generateAllAvailableIp(String startIp, String endIp) {
    	String ip = text_ip.substring(0, text_ip.lastIndexOf(".") + 1);
    	int start = Integer.parseInt(startIp.substring(startIp.lastIndexOf(".") + 1));
    	int end = Integer.parseInt(endIp.substring(endIp.lastIndexOf(".") + 1));
    	List<String> list = new ArrayList<>();
    	for(int i = start;i<end;i++){
    		list.add(ip+i);
    	}
        return list;
    }

    public void searchIp(String currentCheckIp) throws IOException {
        //
        String line;
        String a = null;
        Process pro = Runtime.getRuntime().exec("ping " + currentCheckIp);
        BufferedReader buf = new BufferedReader(new InputStreamReader(pro.getInputStream()));
        int i = 0;
        while ((line = buf.readLine()) != null) {
            a+=line;
        	i++;
            if (i == 7) {
                break;
            }
        }
        if (a.indexOf("TTL") >= 0) {
            LOGGER.info("正在ping :{}", currentCheckIp);
            Device device = new Device();
            device.setStatus(status);
            device.setTyIp(currentCheckIp);
            ipToDeviceMap.put(currentCheckIp, device);
        }
        buf.close();
        String msg = "正在ping设备"+currentCheckIp;
        this.model.setLabel(msg);
    }

    public void searchMac() {
        new Thread(() -> {
            try {
                long start_search_time = System.currentTimeMillis();
                List<String> arpLineList = getArpLineList();
                for (String line : arpLineList) {
                    String parseIpFromArpLine = parseMacFromArpLine(line).trim();
                    String  parseMacFromArpLine = parseIpFromArpLine(line).trim();
                    
                    String productType = ProductManager.get(parseMacFromArpLine.substring(0, 5));
                    if (productType != "未知") {
                        Device device = new Device();
                        device.setTyIp(parseIpFromArpLine);
                        device.setMac(parseMacFromArpLine);
                        device.setProduct(productType);
                        callback.discovery(device);
                        LOGGER.info("搜索到设备:{} mac:{} 产品类型:{}", parseIpFromArpLine, parseMacFromArpLine,productType);
                        this.model.setLabel("已找到设备："+productType);
                    }
                }
                this.model.setLabel("正在等待上传......");
                LOGGER.debug("搜索mac耗时:{}", System.currentTimeMillis() - start_search_time);
            } catch (Exception e) {
                LOGGER.error("搜索mac时发生错误",e);
            }
        }).start();
    }

    private String parseMacFromArpLine(String line) {
        return line.substring(2,15);
    }

    private String parseIpFromArpLine(String line) {
        return line.substring(24, line.length() - 15);
    }

    private List<String> getArpLineList() throws IOException {
        Process p = Runtime.getRuntime().exec("cmd /C arp -a");
        BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
        List<String> list_ip = new ArrayList<>();
        String str;
        while ((str = br.readLine()) != null) {
            if (str.contains("动态̬") || str.contains("dynamic")) {
                list_ip.add(str);
                LOGGER.info("使用ARP命令搜索到有用信息:{}", str);
            }
        }
        return list_ip;
    }

    public void stop() throws IOException {
        isRunnable = false;
    }

    public void setText_ip(String text_ip) {
        this.text_ip = text_ip;
    }

    public void setText_ip1(String text_ip1) {
        this.text_ip1 = text_ip1;
    }
    public String getText_ip1() {
  		return text_ip1;
  	}


}
